"use strict";

var path = require('path'),
    winston = require('./features/logger.js'),
    E = require('./utils/error.js'),
    WebModule = require('./webmodule.js'),
    ConfigError = E.ConfigError,
    SystemDesignError = E.SystemDesignError,
    C = require('./common.js'),
    fs = C.fs,
    _ = C._,
    async = C.async,
    S = C.S;

var App = WebModule.extend({
    /**
     * The app engine object, e.g. express
     * @memberof App#
     * @type {*}
     */
    engine: null,

    /**
     * The app's static documents root
     * @memberof App#
     * @type {string}
     */
    documentRoot: 'webroot',

    nodeframeRoot: path.normalize(__dirname + '/..'),

    /**
     * The nodeframe web application
     * @constructs App
     * @mixes WebModule
     */
    constructor: function() {
        this.base();

        var self = this;

        this.extend({
            loadConfig: function () {
                //Load environment config
                var env, envFile = self.toAbsPath('etc/env.js');

                try {
                    env = require(envFile);
                } catch (err) {
                    console.warn('Unable to load "' + envFile + '"!');
                    console.log('Use "development" as the default env.');
                }

                //If fails to load env
                if (!env) {
                    env = "development";
                } else {
                    C.excludeDotDotInPath('env', env);
                }

                global.ENV = env;

                //Load config by environment
                var cfg, cfgFile = self.toAbsPath('etc/' + env + '.js');

                if (!fs.existsSync(cfgFile)) {
                    cfg = {};

                    console.warn('Config file ["' + cfgFile + '"] not found!');
                    console.log('Use default configuration.');
                } else {
                    var cfgGlobal = { appRoot: self.root, toAbsPath: self.toAbsPath },
                        cfgContent = fs.readFileSync(cfgFile, 'utf8');

                    cfg = C.requireFromString(cfgContent, cfgFile, module, cfgGlobal);
                }

                //Fill defaults
                var cfgDefaultsFile = path.resolve(__dirname, './config-defaults.js'),
                    cfgDefContent = fs.readFileSync(cfgDefaultsFile, 'utf8'),
                    cfgDefaults = C.requireFromString(cfgDefContent, cfgDefaultsFile, module, cfgGlobal);

                self._setConfig(_.defaults(cfg, cfgDefaults));
            },

            /**
             * Bootstrapping the module.
             * @param {object} [options] - bootstrap options
             * @param {completionCallback} cb
             */
            bootstrap: function (options, cb) {
                if (typeof options === 'function' && !cb) {
                    cb = options;
                    options = null;
                }

                process.chdir(self.root);

                self.base(options, function (err) {
                    if (err) return cb && cb(err);

                    console.log('The application has been started successfully.');
                    cb && cb();
                });
            }
        });
    }
});

var app = new App();

module.exports = app;